`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    16:08:50 03/24/2012 
// Design Name: 
// Module Name:    PcieBridge 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module PcieBridge #(
  parameter SIMULATION                  = "FALSE", // Indicates whether SIM or HW
  parameter LANES                       = 4,        // Number of PCIe Lanes
  parameter UP_STREAM = 1
)(
  input PCIE_CLK,                                              // PCIe System Clock - P
  input PCIE_RST,                                              // PCIe System Reset

  output [LANES-1:0] PCIE_TXn,
  output [LANES-1:0] PCIE_TXp,
  input  [LANES-1:0] PCIE_RXn,
  input  [LANES-1:0] PCIE_RXp,

  input               CLK,
  input               RST,
  
  input               S_TVALID,
  output              S_TREADY,
  input   [127:0]     S_TDATA,
  input   [3:0]       S_TSTRB,
  input               S_TLAST,
      
  output              M_TVALID,
  input               M_TREADY,
  output  [127:0]     M_TDATA,
  output  [3:0]       M_TSTRB,
  output              M_TLAST,

  input   [31:0]  S_AWADDR,
  input           S_AWVALID,
  output          S_AWREADY,
  input   [31:0]  S_WDATA,
  input   [3:0]   S_WSTRB,
  input           S_WVALID,
  output          S_WREADY,
  output  [1:0]   S_BRESP,
  output          S_BVALID,
  input           S_BREADY,
  input   [31:0]  S_ARADDR,
  input           S_ARVALID,
  output          S_ARREADY,
  output  [31:0]  S_RDATA,
  output  [1:0]   S_RRESP,
  output          S_RVALID,
  input           S_RREADY,

  output [31:12] io_base,
  output [31:12] io_limit,
  output [31:20] mem_base,
  output [31:20] mem_limit,
  output [63:20] pmem_base,
  output [63:20] pmem_limit,
  output [7:0]   primary_bus,
  output [7:0]   secondary_bus,
  output [7:0]   subordinate_bus,

  output              LINK_UP  
);

  localparam PCIE_CAP_DEVICE_PORT_TYPE = UP_STREAM ? 4'b0101 : 4'b0110;
  localparam UPSTREAM_FACING = UP_STREAM ? "TRUE" : "FALSE";

  wire          ppb_s_pri_tvalid;
  wire          ppb_s_pri_tready;
  wire [127:0]  ppb_s_pri_tdata;
  wire [3:0]    ppb_s_pri_tstrb;
  wire          ppb_s_pri_tlast;
  wire          ppb_m_pri_tvalid;
  wire          ppb_m_pri_tready;
  wire [127:0]  ppb_m_pri_tdata;
  wire [3:0]    ppb_m_pri_tstrb;
  wire          ppb_m_pri_tlast;

  wire          ppb_s_sec_tvalid;
  wire          ppb_s_sec_tready;
  wire [127:0]  ppb_s_sec_tdata;
  wire [3:0]    ppb_s_sec_tstrb;
  wire          ppb_s_sec_tlast;
  wire          ppb_m_sec_tvalid;
  wire          ppb_m_sec_tready;
  wire [127:0]  ppb_m_sec_tdata;
  wire [3:0]    ppb_m_sec_tstrb;
  wire          ppb_m_sec_tlast;

  wire          core_s_tvalid;
  wire          core_s_tready;
  wire [127:0]  core_s_tdata;
  wire [3:0]    core_s_tstrb;
  wire          core_s_tlast;
  wire          core_m_tvalid;
  wire          core_m_tready;
  wire [127:0]  core_m_tdata;
  wire [3:0]    core_m_tstrb;
  wire          core_m_tlast;

  wire [31:0]   cfg_rd_data;
  wire [31:0]   cfg_wr_data;
  wire [3:0]    cfg_byte_en;
  wire [9:0]    cfg_dwaddr;
  wire          cfg_rd_en;
  wire          cfg_wr_en;
  wire          cfg_rd_wr_done;

  wire [31:0]   ppb_CfgDo;
  wire [31:0]   ppb_CfgDi;
  wire [3:0]    ppb_CfgBe;
  wire [9:0]    ppb_CfgAddr;
  wire          ppb_CfgWe;
  wire          ppb_CfgReq;
  wire          ppb_CfgAck;

  generate
    if (UP_STREAM) 
    begin: UP_STREAM_CON
      assign ppb_s_pri_tvalid = core_m_tvalid;
      assign core_m_tready = ppb_s_pri_tready;
      assign ppb_s_pri_tdata = core_m_tdata;
      assign ppb_s_pri_tstrb = core_m_tstrb;
      assign ppb_s_pri_tlast = core_m_tlast;
      assign core_s_tvalid = ppb_m_pri_tvalid;
      assign ppb_m_pri_tready = core_s_tready;
      assign core_s_tdata = ppb_m_pri_tdata;
      assign core_s_tstrb = ppb_m_pri_tstrb;
      assign core_s_tlast = ppb_m_pri_tlast;
      assign ppb_s_sec_tvalid = S_TVALID;
      assign S_TREADY = ppb_s_sec_tready;
      assign ppb_s_sec_tdata = S_TDATA;
      assign ppb_s_sec_tstrb = S_TSTRB;
      assign ppb_s_sec_tlast = S_TLAST;
      assign M_TVALID = ppb_m_sec_tvalid;
      assign ppb_m_sec_tready = M_TREADY;
      assign M_TDATA = ppb_m_sec_tdata;
      assign M_TSTRB = ppb_m_sec_tstrb;
      assign M_TLAST = ppb_m_sec_tlast;
    end 
    else 
    begin: DN_STREAM_CON
      assign ppb_s_pri_tvalid = S_TVALID;
      assign S_TREADY = ppb_s_pri_tready;
      assign ppb_s_pri_tdata = S_TDATA;
      assign ppb_s_pri_tstrb = S_TSTRB;
      assign ppb_s_pri_tlast = S_TLAST;
      assign M_TVALID = ppb_m_pri_tvalid;
      assign ppb_m_pri_tready = M_TREADY;
      assign M_TDATA = ppb_m_pri_tdata;
      assign M_TSTRB = ppb_m_pri_tstrb;
      assign M_TLAST = ppb_m_pri_tlast;
      assign ppb_s_sec_tvalid = core_m_tvalid;
      assign core_m_tready = ppb_s_sec_tready;
      assign ppb_s_sec_tdata = core_m_tdata;
      assign ppb_s_sec_tstrb = core_m_tstrb;
      assign ppb_s_sec_tlast = core_m_tlast;
      assign core_s_tvalid = ppb_m_sec_tvalid;
      assign ppb_m_sec_tready = core_s_tready;
      assign core_s_tdata = ppb_m_sec_tdata;
      assign core_s_tstrb = ppb_m_sec_tstrb;
      assign core_s_tlast = ppb_m_sec_tlast;
    end
  endgenerate

  ppb bridge(
    .CLK            (CLK),
    .RST            (RST),

    .s_pri_tvalid   (ppb_s_pri_tvalid),
    .s_pri_tready   (ppb_s_pri_tready),
    .s_pri_tdata    (ppb_s_pri_tdata ),
    .s_pri_tstrb    (ppb_s_pri_tstrb ),
    .s_pri_tlast    (ppb_s_pri_tlast ),
    .m_pri_tvalid   (ppb_m_pri_tvalid),
    .m_pri_tready   (ppb_m_pri_tready),
    .m_pri_tdata    (ppb_m_pri_tdata ),
    .m_pri_tstrb    (ppb_m_pri_tstrb ),
    .m_pri_tlast    (ppb_m_pri_tlast ),
  
    .s_sec_tvalid   (ppb_s_sec_tvalid),
    .s_sec_tready   (ppb_s_sec_tready),
    .s_sec_tdata    (ppb_s_sec_tdata ),
    .s_sec_tstrb    (ppb_s_sec_tstrb ),
    .s_sec_tlast    (ppb_s_sec_tlast ),
    .m_sec_tvalid   (ppb_m_sec_tvalid),
    .m_sec_tready   (ppb_m_sec_tready),
    .m_sec_tdata    (ppb_m_sec_tdata ),
    .m_sec_tstrb    (ppb_m_sec_tstrb ),
    .m_sec_tlast    (ppb_m_sec_tlast ),

    .CfgDo          (ppb_CfgDo  ),
    .CfgDi          (ppb_CfgDi  ),
    .CfgBe          (ppb_CfgBe  ),
    .CfgAddr        (ppb_CfgAddr),
    .CfgWe          (ppb_CfgWe  ),
    .CfgReq         (ppb_CfgReq ),
    .CfgAck         (ppb_CfgAck ),
    
    .io_base        (io_base        ),
    .io_limit       (io_limit       ),
    .mem_base       (mem_base       ),
    .mem_limit      (mem_limit      ),
    .pmem_base      (pmem_base      ),
    .pmem_limit     (pmem_limit     ),
    .primary_bus    (primary_bus    ),
    .secondary_bus  (secondary_bus  ),
    .subordinate_bus(subordinate_bus)
    );

  PcieCore #(
    .SIMULATION     (SIMULATION),
    .LANES          (LANES),
    .PCIE_CAP_DEVICE_PORT_TYPE(PCIE_CAP_DEVICE_PORT_TYPE),
    .UPSTREAM_FACING(UPSTREAM_FACING))
  core(
    .CLK            (CLK),
    .RST            (RST),
                      
    .rx_tvalid      (core_m_tvalid),
    .rx_tready      (core_m_tready),
    .rx_tdata       (core_m_tdata ),
    .rx_tstrb       (core_m_tstrb ),
    .rx_tlast       (core_m_tlast ),
    .tx_tvalid      (core_s_tvalid),
    .tx_tready      (core_s_tready),
    .tx_tdata       (core_s_tdata ),
    .tx_tstrb       (core_s_tstrb ),
    .tx_tlast       (core_s_tlast ),

    .drp_clk      (pcie_drp_clk   ),
    .drp_den      (pice_drp_den   ),
    .drp_dwe      (pcie_drp_dwe   ),
    .drp_daddr    (pcie_drp_daddr ),
    .drp_di       (pcie_drp_dwdata),
    .drp_drdy     (pcie_drp_drdy  ),
    .drp_do       (pcie_drp_drdata),

    .CfgDo        (ppb_CfgDi),
    .CfgDi        (ppb_CfgDo),
    .CfgBe        (ppb_CfgBe),
    .CfgAddr      (ppb_CfgAddr),
    .CfgWe        (ppb_CfgWe),
    .CfgReq       (ppb_CfgReq),
    .CfgAck       (ppb_CfgAck),
    
    .link_up        (LINK_UP),

    .PCIE_CLK       (PCIE_CLK),
    .PCIE_RST       (PCIE_RST),
    
    .PCIE_TXn       (PCIE_TXn),
    .PCIE_TXp       (PCIE_TXp),
    .PCIE_RXn       (PCIE_RXn),
    .PCIE_RXp       (PCIE_RXp));
  
endmodule
